using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.Experimental.GraphView;
using UnityEngine;
using UnityEngine.UIElements;

namespace DA.AnimGraph.Editor {

    internal class GraphViewService : Service {
        public void SetCenterPosition(Vector3 newPos) {
            (provider as AnimGraphView).SetCenterPosition(newPos);
        }
    }

    internal class AnimGraphView : GraphView {

        private readonly GraphCanvasBase parentPane;
        protected readonly AGEEnvironment AgeEnv;
        NodeCreationMenu nodeCreationMenu;

        public AnimGraphView(GraphCanvasBase graphPane, AGEEnvironment ageEnv) {
            parentPane = graphPane;
            this.AgeEnv = ageEnv;
            AGEGlobal.GetInstance().style.SS_GraphView(this);
            SetupZoom(0.2f, 2);

            this.AddManipulator(new ContentDragger()); //拖动背景
            this.AddManipulator(new SelectionDragger()); //拖动节点
            this.AddManipulator(new RectangleSelector()); //框选

            var grid = new GridBackground();
            Insert(0, grid);
            grid.StretchToParentSize();

            // 添加创建节点菜单
            nodeCreationMenu = ScriptableObject.CreateInstance<NodeCreationMenu>();
            nodeCreationMenu.Init(this);
            nodeCreationRequest = (context) => {
                SearchWindow.Open(new SearchWindowContext(context.screenMousePosition), nodeCreationMenu);
            };
        }

        #region 画布坐标

        public void SetPosition(Vector3 newPos) {
            contentViewContainer.transform.position = newPos;
            contentViewContainer.transform.scale = Vector3.one;
        }
        public void SetCenterPosition(Vector3 newPos) {
            var bound = localBound;
            bound.center = newPos;
            SetPosition(-bound.position);
        }

        #endregion

        /// <summary>
        /// 筛选可以连的port
        /// </summary>
        public override List<Port> GetCompatiblePorts(Port startPort, NodeAdapter nodeAdapter) {
            var compatiblePorts = new List<Port>();
            ports.ForEach((port) => {
                if (startPort != port //非自己
                    && startPort.node != port.node //非相同node
                    && startPort.portType == port.portType //相同类型
                    && startPort.direction != port.direction //不同方向
                   ) {
                    compatiblePorts.Add(port);
                }
            });
            return compatiblePorts;
        }

        /// <summary>
        /// 右键菜单
        /// </summary>
        public override void BuildContextualMenu(ContextualMenuPopulateEvent evt) {
            if (AgeEnv.ageMode == AGEMode.Edit) {
                if (evt.target is GraphView && nodeCreationRequest != null) {
                    evt.menu.AppendAction("Create Node",
                        (a) => RequestNodeCreation(a.eventInfo.mousePosition),
                        DropdownMenuAction.AlwaysEnabled);
                    evt.menu.AppendSeparator();
                }
                if (evt.target is GraphView || evt.target is Node || evt.target is Group) {
                    evt.menu.AppendAction("Cut", delegate {
                        CutSelectionCallback();
                    }, (DropdownMenuAction a) => canCutSelection ? DropdownMenuAction.Status.Normal : DropdownMenuAction.Status.Disabled);
                }
                if (evt.target is GraphView || evt.target is Node || evt.target is Group) {
                    evt.menu.AppendAction("Copy", delegate {
                        CopySelectionCallback();
                    }, (DropdownMenuAction a) => canCopySelection ? DropdownMenuAction.Status.Normal : DropdownMenuAction.Status.Disabled);
                }
                if (evt.target is GraphView) {
                    evt.menu.AppendAction("Paste", delegate {
                        PasteCallback();
                    }, (DropdownMenuAction a) => canPaste ? DropdownMenuAction.Status.Normal : DropdownMenuAction.Status.Disabled);
                }
                if (evt.target is GraphView || evt.target is Node || evt.target is Group || evt.target is Edge) {
                    evt.menu.AppendSeparator();
                    evt.menu.AppendAction("Delete", delegate {
                        DeleteSelectionCallback(AskUser.DontAskUser);
                    }, (DropdownMenuAction a) => canDeleteSelection ? DropdownMenuAction.Status.Normal : DropdownMenuAction.Status.Disabled);
                }
            }
        }

        private void RequestNodeCreation(Vector2 position) {
            if (nodeCreationRequest != null) {
                var window = AgeEnv.ageContext.window;
                var p = window.position.position;
                Vector2 screenMousePosition = p + position;
                nodeCreationRequest(new NodeCreationContext {
                    screenMousePosition = screenMousePosition,
                    target = null,
                    index = -1
                });
            }
        }

        /// <summary>
        /// 创建菜单用
        /// </summary>
        protected class NodeCreationMenu : ScriptableObject, ISearchWindowProvider {

            List<SearchTreeEntry> menuTree;
            AnimGraphView ownerGraph;

            internal void Init(AnimGraphView owner) {
                ownerGraph = owner;
            }

            /// <summary>
            /// 创建节点选择菜单
            /// </summary>
            public List<SearchTreeEntry> CreateSearchTree(SearchWindowContext context) {
                if (menuTree != null) {
                    //不重复构建，看看有没有问题
                    return menuTree;
                }
                menuTree = new List<SearchTreeEntry> {
                    new SearchTreeGroupEntry(new GUIContent("Create Node"), 0)
                };

                var nodeTypeTupleArray = NodeTypeRegister.GetInstance().GetNodesForMenu();
                foreach (var tuple in nodeTypeTupleArray) {

                    var i = 0;
                    // 分类参考：
                    //for(; i < attr.path.Length; i++)
                    //{
                    //    tree.Add(new SearchTreeGroupEntry(new GUIContent(attr.path[i]), i + 1));
                    //}

                    string itemText = Path.GetFileName(tuple.path);
                    menuTree.Add(new SearchTreeEntry(new GUIContent(itemText)) {
                        userData = tuple,
                        level = i + 1
                    });
                }
                return menuTree;
            }

            /// <summary>
            /// 创建节点
            /// </summary>
            public bool OnSelectEntry(SearchTreeEntry SearchTreeEntry, SearchWindowContext context) {
                if (SearchTreeEntry.userData is NodeTypeTuple userData) {
                    // 计算坐标
                    var window = ownerGraph.AgeEnv.ageContext.window;
                    var mousePosition = window.rootVisualElement.ChangeCoordinatesTo(window.rootVisualElement.parent,
                        context.screenMousePosition - window.position.position);
                    var graphMousePosition = ownerGraph.WorldToLocal(mousePosition);
                    graphMousePosition.y -= EditorGUIUtility.singleLineHeight;
                    graphMousePosition = Vector3.Scale(graphMousePosition, Vector3.one) - ownerGraph.viewTransform.position;
                    graphMousePosition *= 1 / ownerGraph.scale;

                    var model = Activator.CreateInstance(userData.nodeModelType) as AGANodeModelBase;
                    ownerGraph.parentPane.ageContext.serviceManager.GetService<AddNodeService>().AddNode(model, userData.agaNodeType, graphMousePosition);
                }
                return true;
            }

        }
    }
}